#ifndef _APP_IP_H_
#define _APP_IP_H_
#include "stm32l0xx_hal.h"
//#include "compiler.h"

#define TX_BUF_LEN   600
#define RX_BUF_LEN   600

#define LONG_BUF_LEN          512
#define SINGLE_PACKET_LEN     19
#define ACK_LEN               1
#define PACKET_GROUP_NUMBER   4

#define ACK_FLAG_MASK         0x80
#define SN_MASK               0x7F


#ifndef BYTE_ORDER
#define BYTE_ORDER     0x3412
#endif /* BYTE_ORDER */

#if BYTE_ORDER == 0x1234
#define HTONS(n) (n)
#define HTONL(n) (n)
#elif BYTE_ORDER == 0x3412

#define HTONS(n) ((((uint16_t)((n) & 0x00ff)) << 8) |   \
                  (((uint16_t)(n) & 0xff00) >> 8))

#define HTONL(n) ((((uint32_t)((n) & 0x000000ff)) << 24) | \
                  (((uint32_t)((n) & 0x0000ff00)) << 8) | \
                  (((uint32_t)((n) & 0x00ff0000)) >> 8) | \
                  (((n) & 0xff000000) >> 24))
#else
#error "endian not set"
#endif

#define htons HTONS
#define htonl HTONL

#define IPADDR(b1, b2, b3, b4)                  \
    (((uint32_t)(b1) << 24) |                             \
     ((uint32_t)(b2) << 16) |                             \
     ((uint32_t)(b3) << 8)  |                             \
     ((uint32_t)(b4)))


typedef __packed struct {
    uint8_t ack;
    uint8_t payload[19];
} ble_data_packet_t;

typedef __packed struct {
    uint32_t ip;
    uint16_t port;
    uint16_t len;
    uint8_t payload[];
} ble_data_packet_hdr_t;

typedef enum {
 app_ip_ok = 0x00,
 app_ip_error
}APP_IP_Status_t;

enum {
 app_ip_tx_enable = 0x00,
 app_ip_tx_disable 
};

extern uint8_t bleDataBufRx[600];
extern uint8_t bleDataBufTx[600];

#define udp_payload_rx         ((uint8_t*)&(bleDataBufRx[0]))
#define udp_hdr_rx                ((ble_data_packet_hdr_t*)&bleDataBufRx[0])
#define udp_payload_len_rx        (htons(udp_hdr_rx->len))

#define udp_payload_tx            ((uint8_t*)&(bleDataBufTx[0]))
#define udp_hdr_tx                ((ble_data_packet_hdr_t*)&bleDataBufTx[0])
#define udp_payload_len_tx        (htons(udp_hdr_tx->len))

/*Private function*/
void app_ip_rx_receive_data(uint8_t* data, uint8_t len);
void app_ip_tx_receive_ack(uint8_t data);
void app_tftp_to_ip(uint16_t len);
void app_ip_tx_responce_to_ack(void);
void app_ip_tx(void);
void app_ip_update_value_callback(uint8_t status);
#endif //_APP_IP_H_

